package com.foreverwin.mes.production.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.core.base.FrontPage;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.CommonMethods;
import com.foreverwin.mes.meapi.model.BomComponent;
import com.foreverwin.mes.meapi.model.CustomFields;
import com.foreverwin.mes.meapi.model.ItemGroupMember;
import com.foreverwin.mes.meapi.model.SfcBom;
import com.foreverwin.mes.meapi.service.BomComponentService;
import com.foreverwin.mes.meapi.service.CustomFieldsService;
import com.foreverwin.mes.meapi.service.ItemGroupMemberService;
import com.foreverwin.mes.meapi.service.SfcBomService;
import com.foreverwin.mes.production.constant.Constants;
import com.foreverwin.mes.production.dto.ResourceInventoryDto;
import com.foreverwin.mes.production.mapper.ResourceInventoryMapper;
import com.foreverwin.mes.production.model.ResourceInventory;
import com.foreverwin.mes.production.service.ResourceInventoryService;
import com.foreverwin.mes.production.support.LoadStrategy;
import com.foreverwin.mes.production.support.LoadStrategyFactory;
import com.foreverwin.mes.production.support.UnloadStrategy;
import com.foreverwin.mes.production.support.UnloadStrategyFactory;
import com.foreverwin.mes.production.vo.ResourceInventoryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

/**
 * <p>
 * 设备库存 服务实现类
 * </p>
 *
 * @author Ervin Chen
 * @since 2020-02-04
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ResourceInventoryServiceImpl extends ServiceImpl<ResourceInventoryMapper, ResourceInventory> implements ResourceInventoryService {

    @Autowired
    private ResourceInventoryMapper resourceInventoryMapper;
    @Autowired
    private CustomFieldsService customFieldsService;
    @Autowired
    private ItemGroupMemberService itemGroupMemberService;
    @Autowired
    private SfcBomService sfcBomService;
    @Autowired
    private BomComponentService bomComponentService;

    @Override
    public Page<ResourceInventory> selectPage(FrontPage<ResourceInventory> frontPage, ResourceInventory resourceInventory) {
        EntityWrapper<ResourceInventory> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(resourceInventory);
        return super.selectPage(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<ResourceInventory> selectList(ResourceInventory resourceInventory) {
        EntityWrapper<ResourceInventory> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(resourceInventory);
        return super.selectList(queryWrapper);
    }

    @Override
    public List<ResourceInventoryVo> selectResourceInventoryList(ResourceInventory resourceInventory) {
        EntityWrapper<ResourceInventory> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(resourceInventory);
        queryWrapper.gt( "qty_on_hand", 0 ).or().isNull("qty_on_hand");
        Locale locale = LocaleContextHolder.getLocale();
        return resourceInventoryMapper.selectResourceInventoryList(locale.getLanguage(), queryWrapper);
    }

    @Override
    public boolean insertOrUpdate(List<ResourceInventoryDto> resourceInventoryDtos) {
        for( ResourceInventoryDto resourceInventoryDto : resourceInventoryDtos ){
            String itemBo = resourceInventoryDto.getItemBo();
            String loadMode = getItemLoadMode(itemBo);
            resourceInventoryDto.setLoadMode(loadMode);
            //上料
            if( resourceInventoryDto.getActionCode() == 0 ){
                LoadStrategy loadStrategy = LoadStrategyFactory.getLoadStrategy( loadMode );
                loadStrategy.initService();
                loadStrategy.validate(resourceInventoryDto);
                loadStrategy.load(resourceInventoryDto);
            }
            //卸料
            else if( resourceInventoryDto.getActionCode() == 1 ){
                UnloadStrategy unloadStrategy = UnloadStrategyFactory.getUnloadStrategy( loadMode );
                unloadStrategy.initService();
                unloadStrategy.validate( resourceInventoryDto );
                unloadStrategy.unload( resourceInventoryDto );
            }
        }
        return true;
    }

    @Override
    public String getItemLoadMode( String itemBo ){
        String itemGroupBo = getItemGroupByItem( itemBo );
        CustomFields customFields = new CustomFields();
        customFields.setHandle( itemGroupBo );
        customFields.setAttribute( Constants.ITEM_CONTROL_TYPE );
        List<CustomFields> customFieldsList = customFieldsService.selectList(customFields);
        if( customFieldsList.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.itemLoadModeNotExist", HandleEnum.ITEM.getPart( itemBo, 1 ) );
        }
        return customFieldsList.get(0).getValue();
    }

    public double getItemUpperDeviation( String itemBo ){
        CustomFields customFields = new CustomFields();
        customFields.setHandle(itemBo);
        customFields.setAttribute(Constants.UP_DEVIATION);
        List<CustomFields> customFieldsList = customFieldsService.selectList(customFields);
        if( customFieldsList.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.itemUpperDeviationNotExist", HandleEnum.ITEM.getPart( itemBo, 1 ) );
        }
        String value = customFieldsList.get(0).getValue();
        return Double.parseDouble( value );
    }

    public double getItemLowerDeviation( String itemBo ){
        CustomFields customFields = new CustomFields();
        customFields.setHandle(itemBo);
        customFields.setAttribute(Constants.LOW_DEVIATION);
        List<CustomFields> customFieldsList = customFieldsService.selectList(customFields);
        if( customFieldsList.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.itemLowerDeviationNotExist", HandleEnum.ITEM.getPart( itemBo, 1 ) );
        }
        String value = customFieldsList.get(0).getValue();
        return Double.parseDouble( value );
    }

    public List<String> getResourceLoadItems( String resource ){
        String site = CommonMethods.getSite();
        CustomFields customFields = new CustomFields();
        customFields.setHandle( HandleEnum.RESOURCE.getHandle( site, resource ) );
        customFields.setAttribute( Constants.LOAD_ITEMS );
        return customFieldsService.selectList( customFields )
                                  .stream()
                                  .map( customField -> customField.getValue() )
                                  .collect( Collectors.toList() );
    }

    public List<String> getResourceLoadItemGroups( String resource ){
        String site = CommonMethods.getSite();
        CustomFields customFields = new CustomFields();
        customFields.setHandle( HandleEnum.RESOURCE.getHandle( site, resource ) );
        customFields.setAttribute( Constants.LOAD_ITEM_GROUPS );
        return customFieldsService.selectList( customFields )
                                  .stream()
                                  .map( customField -> customField.getValue() )
                                  .collect( Collectors.toList() );
    }

    /**
     * 检验设备是否可以上料物料
     * @param resource
     * @param itemBo
     * @return
     */
    public boolean validateResourceLoadItem( String resource, String itemBo ){
        List<String> validItems = getResourceLoadItems( resource );
        List<String> validItemGroups = getResourceLoadItemGroups( resource );
        if( validItems.isEmpty() && validItemGroups.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.resourceLoadItemsNotExist", resource );
        }
        if( !validItems.isEmpty() ){
            if( !validItems.contains( HandleEnum.ITEM.getPart( itemBo, 1 ) ) ){
                throw BusinessException.build( "production.resourceInventory.resourceNotAllowLoadItem", resource, HandleEnum.ITEM.getPart( itemBo, 1 ) );
            }
        }else{
            String itemGroupBo = getItemGroupByItem( itemBo );
            String itemGroup = HandleEnum.ITEM_GROUP.getPart(itemGroupBo,1);
            if( !validItemGroups.contains( itemGroup ) ){
                throw BusinessException.build( "production.resourceInventory.resourceNotAllowLoadItem", resource, HandleEnum.ITEM.getPart( itemBo, 1 ) );
            }
        }
        return true;
    }

    public String getItemGroupByItem( String itemBo ){
        ItemGroupMember queryEntity = new ItemGroupMember();
        queryEntity.setItemBo( itemBo );
        List<ItemGroupMember> itemGroupMembers = itemGroupMemberService.selectList( queryEntity );
        if( itemGroupMembers.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.itemNotExistItemGroup", HandleEnum.ITEM.getPart( itemBo, 1 ) );
        }else{
            return itemGroupMembers.get( 0 ).getItemGroupBo();
        }
    }

    /**
     * 校验设备上料物料是否符合BOM
     * @param sfc
     * @param operation
     * @param itemBo
     * @return
     */
    public boolean validateResourceLoadItemMatchBom( String sfc, String operation, String itemBo ){
        String site = CommonMethods.getSite();
        String sfcBo = HandleEnum.SFC.getHandle( site, sfc );

        SfcBom queryEntity = new SfcBom();
        queryEntity.setSfcBo( sfcBo );
        List<SfcBom> sfcBoms = sfcBomService.selectList( queryEntity );
        if( sfcBoms.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.sfcBomNotExist", sfc );
        }

        String bomBo = sfcBoms.get( 0 ).getBomBo();
        String operationBo = HandleEnum.OPERATION.getHandle( site, operation, "#" );
        EntityWrapper<BomComponent> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq( "bom_bo", bomBo )
                     .eq( "component_gbo", itemBo );
        List<BomComponent> bomComponents = bomComponentService.selectBomComponentByOperation( entityWrapper, operationBo );
        if( bomComponents.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.loadItemNotMatchBom", HandleEnum.ITEM.getPart( itemBo, 1 ) );
        }

        return true;
    }

    public boolean isProductionResource(String site, String resource){
        String resourceBo = HandleEnum.RESOURCE.getHandle(site, resource);
        CustomFields customFields = new CustomFields();
        customFields.setHandle(resourceBo);
        customFields.setAttribute(Constants.NO_PRD_RESOURCE);
        List<CustomFields> customFieldsList = customFieldsService.selectList(customFields);
        if(customFieldsList.isEmpty()){
            return true;
        }else{
            String value = customFieldsList.get(0).getValue();
            if("Y".equals(value)){
                return false;
            }else{
                return true;
            }
        }
    }
}